


/**promisify - 把回调函数变为Promise方式
 * @param fn 任何需要调用回调函数的函数，默认最后一个参数是回调函数
 * @returns 返回一个Promise，then的参数是一个数组，装着原callback的参数
 * @example
 * function foo(a: string, b: number, callback: (a: string, b: number) => any) {
 *    setTimeout(() => { 
 *        callback(a, b)
 *    }, 1000)
 * }
 * const newFn = promisify(foo)
 * newFn('hello', 666).then(console.log) // ['hello', 666]
 */
function promisify<T extends (...arg: any[]) => void>(fn: T) {
    //返回一个新函数，这个新函数，传递老函数的参数（除了最后的回调）
    //本质是，本函数内部帮你把回调函数调用了，得到结果之后，resolve出去
    return function (...arg: TupleInit<Parameters<T>>) {
        type CallbackParam = Parameters<TupleLast<Parameters<T>>> //回调函数的参数类型
        return new Promise<CallbackParam>((resolve, reject) => {
            /**内部自制的回调函数 */
            const callback = (...arg2: CallbackParam) => {
                resolve(arg2)//把回调得到的结果resolve出去
            }
            fn.apply(null, [...arg, callback]) //在这里调用内部自制的回调函数  （原本是用户传入回调）
        })
    }
}
export default promisify


//无类型版：
function promisify_js(fn: any) {
    return function (...arg: any[]) {
        return new Promise((resolve, reject) => {
            const callback = (...arg2: any[]) => {
                resolve(arg2)
            }
            fn.apply(null, [...arg, callback])
        })
    }
}




/**去除第一个元素 */
type TupleTail<T extends any[]> = T extends [x: any, ...other: infer R] ? R : []
/**取得最后一个元素 */
type TupleLast<T extends any[]> = T extends [x: any, ...other: infer R] ? T[R['length']] : never
/**去除最后一个元素 */
type TupleInit<T extends any[]> = T extends [...f: infer R1, l: infer _R2] ? R1 : never
/**从头部加入一个元素 */
type TupleUnshift<T extends any[], X> = [X, ...T]
/**从尾部加入一个元素 */
type TuplePush<T extends any[], X> = [...T, X]
/**连接两个元组 */
type TupleConcat<A extends any[], B extends any[]> = [...A, ...B]